use axum::{extract::{Path, State}, Json};
use serde::Deserialize;
use sqlx::{Pool, Sqlite};

use crate::db::{get_user_counter, Counter};

use super::{jwt::Claims, ApiError};

pub async fn list (
    claims: Claims,
    State(pool): State<Pool<Sqlite>>,
) -> Result<Json<Vec<Counter>>, ApiError> {
    let user_id = claims.get_user_id();

    let counters = sqlx::query_as::<_, Counter>(
        "select * from counters where user_id = ? order by sequence desc",
        )
        .bind(user_id)
        .fetch_all(&pool)
        .await?;

    Ok(Json(counters))
}

#[derive(Debug, Deserialize)]
pub struct AddPayload {
    pub name: String,
    pub value: i32,
    pub step: i32,
    pub input_step: bool,
}

//根据user_id添加一条计数器的记录
pub async fn add (
    claims: Claims,
    State(pool): State<Pool<Sqlite>>,
    Json(payload): Json<AddPayload>,
) -> Result<Json<serde_json::Value>, ApiError> {
    let user_id = claims.get_user_id();

    let sequence = sqlx::query_as::<_, (i32,)>(
            "select sequence from counters where user_id = ? order by sequence desc limit 1",
        )
        .bind(user_id)
        .fetch_one(&pool)
        .await;
    
    let sequence = match sequence {
        Ok((n,)) => n + 1,
        Err(sqlx::Error::RowNotFound) => 0,
        Err(err) => return Err(ApiError::from(err)),
    };

    sqlx::query("insert into counters (user_id, name, value, step, input_step, sequence) values (?, ?, ?, ?, ?, ?)")
        .bind(user_id)
        .bind(payload.name)
        .bind(payload.value)
        .bind(payload.step)
        .bind(payload.input_step)
        .bind(sequence)
        .execute(&pool)
        .await?;

    Ok(Json(serde_json::json!({"message": "ok"})))

}


pub async fn show (
    claims: Claims,
    State(pool): State<Pool<Sqlite>>,
    Path(id): Path<i32>,
) -> Result<Json<Counter>, ApiError> {
    let user_id = claims.get_user_id();
    let counter = get_user_counter(id, user_id, &pool).await?;
    Ok(Json(counter))
}


#[derive(Debug, Deserialize)]
pub struct UpdatePayload {
    pub name: String,
    pub step: i32,
    pub input_step: bool,
}

//根据id修改一条计数器的记录
pub async fn update (
    Path(id): Path<i32>,
    claims: Claims,
    State(pool): State<Pool<Sqlite>>,
    Json(payload): Json<UpdatePayload>,
) -> Result<Json<serde_json::Value>, ApiError> {
    let user_id = claims.get_user_id();
    let counter = get_user_counter(id, user_id, &pool).await?;
    sqlx::query("update counters set name = ?, step = ?, input_step = ?, updated_at = current_timestamp where id = ?")
        .bind(payload.name)
        .bind(payload.step)
        .bind(payload.input_step)
        .bind(counter.id)
        .execute(&pool)
        .await?;

    Ok(Json(serde_json::json!({"message": "ok"})))
}


pub async fn destroy (
    Path(id): Path<i32>,
    claims: Claims,
    State(pool): State<Pool<Sqlite>>,
) -> Result<Json<serde_json::Value>, ApiError> {
    let user_id = claims.get_user_id();
    get_user_counter(id, user_id, &pool).await?;

    sqlx::query(
        r#"delete from counters where id = ?;delete from counter_records where counter_id = ?"#,
        )
        .bind(id)
        .bind(id)
        .execute(&pool)
        .await?;

    Ok(Json(serde_json::json!({"message": "ok"})))
}

